<script lang="ts" setup>
import { h, onMounted, reactive, ref, computed } from 'vue';
import {
  Card,
  Table,
  Form,
  Input,
  Select,
  Button,
  Space,
  Tag,
  Modal,
  message,
  Upload,
  Descriptions,
} from 'ant-design-vue';
import type { TableColumnsType } from 'ant-design-vue';
import type { RcFile, UploadFile, UploadProps } from 'ant-design-vue/es/upload/interface';
import {
  acceptInvoice,
  getAdminInvoices,
  getAdminInvoiceStatusOptions,
  rejectInvoice,
  uploadInvoiceFile,
  voidInvoice,
  previewInvoiceFile,
  type AdminInvoiceApi,
} from '#/api/core';

const loading = ref(false);
const statusOptions = ref<AdminInvoiceApi.StatusOption[]>([]);
const dataSource = ref<AdminInvoiceApi.InvoiceRecord[]>([]);
const statusFilter = ref<string>();
const tenantKeyword = ref('');

const pagination = reactive({
  current: 1,
  pageSize: 15,
  total: 0,
});

const actionLoadingId = ref<string | null>(null);

const columns: TableColumnsType<AdminInvoiceApi.InvoiceRecord> = [
  {
    title: '申请单号',
    dataIndex: 'invoice_number',
    key: 'invoice_number',
    width: 160,
    ellipsis: true,
  },
  {
    title: '租户',
    dataIndex: ['tenant', 'name'],
    key: 'tenant_name',
    width: 180,
    ellipsis: true,
    customRender: ({ record }) => record.tenant?.company_name || record.tenant?.name || '-',
  },
  {
    title: '开票金额',
    dataIndex: 'invoice_amount',
    key: 'invoice_amount',
    width: 120,
    align: 'right',
    customRender: ({ text }) => `¥${Number(text || 0).toLocaleString()}`,
  },
  {
    title: '开票类型',
    dataIndex: 'billing_type_display',
    key: 'billing_type_display',
    width: 100,
  },
  {
    title: '落地公司',
    dataIndex: ['landing_company', 'name'],
    key: 'landing_company_name',
    width: 180,
    ellipsis: true,
  },
  {
    title: '状态',
    dataIndex: 'status',
    key: 'status',
    width: 110,
    customRender: ({ record }) =>
      h(
        Tag,
        { color: statusColorMap.value[record.status] ?? 'default' },
        () => record.status,
      ),
  },
  {
    title: '申请时间',
    dataIndex: 'application_time',
    key: 'application_time',
    width: 180,
    customRender: ({ text }) => formatDate(text),
  },
  {
    title: '操作',
    key: 'actions',
    width: 220,
    fixed: 'right',
    customRender: ({ record }) => {
      const buttons: JSX.Element[] = [];

      if (record.status === '新建') {
        buttons.push(
          h(
            Button,
            {
              type: 'link',
              loading: actionLoadingId.value === `accept-${record.id}`,
              onClick: () => handleAccept(record),
            },
            () => '受理',
          ),
        );
        buttons.push(
          h(
            Button,
            {
              type: 'link',
              danger: true,
              loading: actionLoadingId.value === `reject-${record.id}`,
              onClick: () => openRejectModal(record),
            },
            () => '拒绝',
          ),
        );
      }

      if (record.status === '开票中') {
        buttons.push(
          h(
            Button,
            {
              type: 'link',
              loading: actionLoadingId.value === `upload-${record.id}`,
              onClick: () => openUploadModal(record),
            },
            () => '上传发票',
          ),
        );
        buttons.push(
          h(
            Button,
            {
              type: 'link',
              danger: true,
              loading: actionLoadingId.value === `reject-${record.id}`,
              onClick: () => openRejectModal(record),
            },
            () => '拒绝',
          ),
        );
      }

      if (record.status === '已开票') {
        buttons.push(
          h(
            Button,
            {
              type: 'link',
              danger: true,
              loading: actionLoadingId.value === `void-${record.id}`,
              onClick: () => handleVoid(record),
            },
            () => '作废',
          ),
        );
      }

      if (record.invoice_file_path) {
        buttons.push(
          h(
            Button,
            {
              type: 'link',
              size: 'small',
              onClick: () => handlePreview(record),
            },
            () => '预览',
          ),
        );
      }

      if (buttons.length === 0) {
        return h('span', { style: { color: '#94a3b8' } }, '—');
      }

      return h(
        Space,
        { size: 8 },
        () => buttons,
      );
    },
  },
];

const statusColorMap = computed<Record<string, string>>(() => ({
  新建: 'default',
  开票中: 'processing',
  已开票: 'success',
  已拒绝: 'error',
  已作废: 'warning',
}));

const fetchStatusOptions = async () => {
  const response = await getAdminInvoiceStatusOptions();
  statusOptions.value = response;
};

const fetchInvoices = async () => {
  loading.value = true;
  try {
    const response = await getAdminInvoices({
      page: pagination.current,
      per_page: pagination.pageSize,
      status: statusFilter.value || undefined,
      tenant_keyword: tenantKeyword.value || undefined,
    });
    dataSource.value = response.items;
    pagination.total = response.pagination.total;
  } finally {
    loading.value = false;
  }
};

const handleTableChange = (pager: {
  current?: number;
  pageSize?: number;
}) => {
  if (pager.current) pagination.current = pager.current;
  if (pager.pageSize) pagination.pageSize = pager.pageSize;
  fetchInvoices();
};

const resetFilters = () => {
  statusFilter.value = undefined;
  tenantKeyword.value = '';
  pagination.current = 1;
  fetchInvoices();
};

const handleAccept = async (record: AdminInvoiceApi.InvoiceRecord) => {
  actionLoadingId.value = `accept-${record.id}`;
  try {
    await acceptInvoice(record.id);
    message.success('已受理开票申请');
    fetchInvoices();
  } finally {
    actionLoadingId.value = null;
  }
};

const rejectModalVisible = ref(false);
const rejectReason = ref('');
const rejectTarget = ref<AdminInvoiceApi.InvoiceRecord | null>(null);

const openRejectModal = (record: AdminInvoiceApi.InvoiceRecord) => {
  rejectTarget.value = record;
  rejectReason.value = '';
  rejectModalVisible.value = true;
};

const submitReject = async () => {
  if (!rejectTarget.value) return;
  if (!rejectReason.value.trim()) {
    message.warning('请输入拒绝原因');
    return;
  }
  actionLoadingId.value = `reject-${rejectTarget.value.id}`;
  try {
    await rejectInvoice(rejectTarget.value.id, rejectReason.value.trim());
    message.success('已拒绝开票申请');
    rejectModalVisible.value = false;
    fetchInvoices();
  } finally {
    actionLoadingId.value = null;
  }
};

const uploadModalVisible = ref(false);
const uploadTarget = ref<AdminInvoiceApi.InvoiceRecord | null>(null);
const expressNumber = ref('');
const uploadFileList = ref<UploadFile[]>([]);
const uploadRawFile = ref<RcFile | null>(null);

const previewModalVisible = ref(false);
const previewLoading = ref(false);
const previewUrl = ref<string | null>(null);

const uploadProps: UploadProps = {
  beforeUpload: (file) => {
    uploadRawFile.value = file as RcFile;
    uploadFileList.value = [file];
    return false;
  },
  onRemove: () => {
    uploadFileList.value = [];
    uploadRawFile.value = null;
  },
};

const openUploadModal = (record: AdminInvoiceApi.InvoiceRecord) => {
  uploadTarget.value = record;
  expressNumber.value = record.express_tracking_number || '';
  uploadFileList.value = [];
  uploadRawFile.value = null;
  uploadModalVisible.value = true;
};

const handleUploadModalCancel = () => {
  uploadModalVisible.value = false;
  uploadFileList.value = [];
  uploadRawFile.value = null;
};

const submitUpload = async () => {
  if (!uploadTarget.value) return;
  if (!uploadRawFile.value) {
    message.warning('请上传发票文件');
    return;
  }
  const formData = new FormData();
  formData.append('invoice_file', uploadRawFile.value);
  if (expressNumber.value) {
    formData.append('express_tracking_number', expressNumber.value);
  }

  actionLoadingId.value = `upload-${uploadTarget.value.id}`;
  try {
    await uploadInvoiceFile(uploadTarget.value.id, formData);
    message.success('发票上传成功');
    handleUploadModalCancel();
    fetchInvoices();
  } finally {
    actionLoadingId.value = null;
  }
};

const handleVoid = (record: AdminInvoiceApi.InvoiceRecord) => {
  Modal.confirm({
    title: '确认作废该发票申请？',
    content: '作废后发票状态将变更为“已作废”，请确认相关业务流程。',
    okText: '确认',
    okButtonProps: { danger: true },
    cancelText: '取消',
    async onOk() {
      actionLoadingId.value = `void-${record.id}`;
      try {
        await voidInvoice(record.id);
        message.success('已作废发票申请');
        fetchInvoices();
      } finally {
        actionLoadingId.value = null;
      }
    },
  });
};

const handlePreview = async (record: AdminInvoiceApi.InvoiceRecord) => {
  if (!record.invoice_file_path) {
    message.warning('暂无可预览的发票文件');
    return;
  }

  if (previewUrl.value) {
    URL.revokeObjectURL(previewUrl.value);
    previewUrl.value = null;
  }

  previewLoading.value = true;
  previewModalVisible.value = true;

  try {
    const blob = await previewInvoiceFile(record.id);
    if (previewUrl.value) {
      URL.revokeObjectURL(previewUrl.value);
    }
    previewUrl.value = URL.createObjectURL(blob);
  } catch (error) {
    console.error('预览发票失败', error);
    message.error('预览发票失败，请稍后重试');
    closePreviewModal();
  } finally {
    previewLoading.value = false;
  }
};

const closePreviewModal = () => {
  previewModalVisible.value = false;
  previewLoading.value = false;
  if (previewUrl.value) {
    URL.revokeObjectURL(previewUrl.value);
    previewUrl.value = null;
  }
};

const currentDetail = ref<AdminInvoiceApi.InvoiceRecord | null>(null);
const detailVisible = ref(false);

const openDetail = (record: AdminInvoiceApi.InvoiceRecord) => {
  currentDetail.value = record;
  detailVisible.value = true;
};

const formatDate = (value?: string | null) => {
  if (!value) return '—';
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value;
  return date.toLocaleString('zh-CN', { hour12: false });
};

const formatRelatedTasks = (value?: string | null) => {
  if (!value) return '';
  try {
    const parsed = JSON.parse(value);
    if (Array.isArray(parsed)) {
      return parsed.join('，');
    }
  } catch (error) {
    // ignore
  }
  return String(value).split(/\n+/).join('，');
};

const filterForm = reactive({
  status: undefined as string | undefined,
  tenant: '',
});

const applyFilters = () => {
  statusFilter.value = filterForm.status;
  tenantKeyword.value = filterForm.tenant;
  pagination.current = 1;
  fetchInvoices();
};

onMounted(async () => {
  await fetchStatusOptions();
  await fetchInvoices();
});
</script>

<template>
  <div class="p-5">
    <Card title="开票管理" :bordered="false">
      <template #extra>
        <Space>
          <Form layout="inline" :model="filterForm">
            <Form.Item label="状态">
              <Select
                v-model:value="filterForm.status"
                placeholder="全部状态"
                allow-clear
                style="width: 150px"
              >
                <Select.Option
                  v-for="option in statusOptions"
                  :key="option.value"
                  :value="option.value"
                >
                  {{ option.label }}
                </Select.Option>
              </Select>
            </Form.Item>
            <Form.Item label="租户">
              <Input
                v-model:value="filterForm.tenant"
                placeholder="租户名称"
                allow-clear
                style="width: 200px"
              />
            </Form.Item>
          </Form>
          <Space>
            <Button type="primary" @click="applyFilters" :loading="loading">
              查询
            </Button>
            <Button @click="resetFilters">重置</Button>
          </Space>
        </Space>
      </template>

      <Table
        :columns="columns"
        :data-source="dataSource"
        :loading="loading"
        :pagination="false"
        row-key="id"
        :scroll="{ x: 1200 }"
        @change="handleTableChange"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'invoice_number'">
            <a @click="openDetail(record)">{{ record.invoice_number }}</a>
          </template>
        </template>
      </Table>

      <div class="flex justify-end mt-4">
        <a-pagination
          :current="pagination.current"
          :page-size="pagination.pageSize"
          :total="pagination.total"
          show-size-changer
          show-quick-jumper
          @change="(page, pageSize) => handleTableChange({ current: page, pageSize })"
          @showSizeChange="(_, size) => handleTableChange({ current: 1, pageSize: size })"
        />
      </div>
    </Card>

    <Modal
      v-model:open="rejectModalVisible"
      title="拒绝开票申请"
      :confirm-loading="actionLoadingId?.startsWith('reject-')"
      @ok="submitReject"
      @cancel="() => (rejectModalVisible = false)"
    >
      <p class="text-gray-500 mb-3">
        请填写拒绝原因，以便租户了解反馈。
      </p>
      <a-textarea
        v-model:value="rejectReason"
        :rows="4"
        placeholder="请输入拒绝原因"
        maxLength="500"
        show-count
      />
    </Modal>

    <Modal
      v-model:open="uploadModalVisible"
      title="上传发票"
      :confirm-loading="actionLoadingId?.startsWith('upload-')"
      @ok="submitUpload"
      @cancel="handleUploadModalCancel"
    >
      <Space direction="vertical" style="width: 100%">
        <Upload v-bind="uploadProps" :file-list="uploadFileList" accept=".pdf,.jpg,.jpeg,.png">
          <Button type="dashed">选择发票文件</Button>
        </Upload>
        <Input
          v-model:value="expressNumber"
          placeholder="快递单号（可选）"
          allow-clear
        />
        <p class="text-gray-500 text-xs">支持 pdf、jpg、jpeg、png，大小不超过 10 MB。</p>
      </Space>
    </Modal>

    <Modal
      v-model:open="previewModalVisible"
      title="发票预览"
      :footer="null"
      width="80%"
      @cancel="closePreviewModal"
      @afterClose="closePreviewModal"
      destroy-on-close
    >
      <div v-if="previewLoading" style="height: 480px; display: flex; align-items: center; justify-content: center;">
        正在加载发票...
      </div>
      <iframe
        v-else-if="previewUrl"
        :src="previewUrl"
        style="width: 100%; height: 480px; border: none;"
      ></iframe>
      <p v-else class="text-gray-500">暂无发票文件。</p>
    </Modal>

    <Modal
      v-model:open="detailVisible"
      title="开票申请详情"
      :footer="null"
      :width="720"
    >
      <Descriptions
        v-if="currentDetail"
        :column="2"
        colon
        bordered
        size="small"
        label-style="{ width: '160px' }"
      >
        <Descriptions.Item label="申请单号">{{ currentDetail.invoice_number }}</Descriptions.Item>
        <Descriptions.Item label="状态">
          <Tag :color="statusColorMap[currentDetail.status]">
            {{ currentDetail.status }}
          </Tag>
        </Descriptions.Item>
        <Descriptions.Item label="租户">{{ currentDetail.tenant?.company_name || currentDetail.tenant?.name || '-' }}</Descriptions.Item>
        <Descriptions.Item label="落地公司">{{ currentDetail.landing_company?.name || '-' }}</Descriptions.Item>
        <Descriptions.Item label="开票金额">
          <span class="text-primary font-semibold">
            ¥{{ Number(currentDetail.invoice_amount).toLocaleString() }}
          </span>
        </Descriptions.Item>
        <Descriptions.Item label="开票类型">{{ currentDetail.billing_type_display }}</Descriptions.Item>
        <Descriptions.Item label="税号">{{ currentDetail.tax_number }}</Descriptions.Item>
        <Descriptions.Item label="开票内容" :span="2">{{ currentDetail.invoice_content }}</Descriptions.Item>
        <Descriptions.Item label="关联任务" :span="2">{{ formatRelatedTasks(currentDetail.related_tasks) || '—' }}</Descriptions.Item>
        <Descriptions.Item label="备注" :span="2">{{ currentDetail.invoice_remarks || '—' }}</Descriptions.Item>
        <Descriptions.Item label="申请时间">{{ formatDate(currentDetail.application_time) }}</Descriptions.Item>
        <Descriptions.Item label="处理时间">{{ formatDate(currentDetail.processed_at) }}</Descriptions.Item>
        <Descriptions.Item label="开票时间">{{ formatDate(currentDetail.issued_at) }}</Descriptions.Item>
        <Descriptions.Item label="拒绝原因" :span="2">
          <span class="text-red-500">{{ currentDetail.rejection_reason || '—' }}</span>
        </Descriptions.Item>
        <Descriptions.Item label="发票文件路径" :span="2">
          {{ currentDetail.invoice_file_path || '—' }}
        </Descriptions.Item>
        <Descriptions.Item label="快递单号" :span="2">
          {{ currentDetail.express_tracking_number || '—' }}
        </Descriptions.Item>
      </Descriptions>
    </Modal>
  </div>
</template>

<style scoped>
.text-primary {
  color: #1890ff;
}
</style>
